package webbrow.board.spring.controller;


import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import webbrow.board.component.BoardReplyService;
import webbrow.board.component.BoardReportService;
import webbrow.board.component.BoardSpringService;
import webbrow.board.vo.BoardSpringVO;
import webbrow.board.vo.CategoryVO;
import webbrow.board.vo.ListVO;
import webbrow.board.vo.MultiFileVO;
import webbrow.member.model.MemberService;

@Controller
public class BoardController  {
	/**
	 * 파일 업로드 할 경로(path)
	 * 우선은 경로를 직접 명시하였고 기본구현 완료 시 업데이트 예정
	 */
	private String path="C:\\java-kosta\\servers\\webbrow-tomcat\\webapps\\webbrow-ver1.0\\useruploadfile\\";	
	@Resource(name="boardSpringService")
	private BoardSpringService service;
	
	@Resource(name="boardReplyService")
	private BoardReplyService boardReplyService;
	 
	@Resource(name="boardReportService")
	private BoardReportService boardReportService;
	
	@Resource(name = "memberServiceImpl")
	private MemberService memberService;
	/**
	 * list_main.jsp 에서 글쓰기 버튼을 클릭하면
	 * registerForm 으로 이동시켜준다.
	 */
	@RequestMapping("writeBtn.inven")
	public String write(){
		return "register.tiles";
	}
	/**
	 * writeContent
	 * 글쓰기 & 멀티파일 업로드
	 */
	@RequestMapping("writeContent.inven")
	public ModelAndView writeContent(BoardSpringVO vo, MultiFileVO mvo) throws Exception{
		System.out.println("controller ref = "+vo);
		List<MultipartFile> list=mvo.getFile();	
		String nameList[]=new String[list.size()];
		String fnStr="";
		String saveStr="";
		for(int i=0;i<list.size();i++){
			String fileName=list.get(i).getOriginalFilename();
			if(!fileName.isEmpty()){
				String newfilename=System.currentTimeMillis()+"_"+fileName;
				if(i==0) {
					fnStr+=fileName;
					saveStr+=newfilename;
				} else {
					fnStr+=","+fileName;
					saveStr+=","+newfilename;
				}
				list.get(i).transferTo(new File(path+newfilename));
				nameList[i]=fileName;
				vo.setOrgFileName(fnStr);
				vo.setSaveFileName(saveStr);
			}
		}
		service.writeSpringBoard(vo);
		return new ModelAndView("redirect:/showContentNoHits.inven?no="+vo.getNo());
	}
	/**
	 * showContentNoHit
	 * 게시물의 조회수(hits) 가 증가하지 않고 글의 내용을 보여준다.
	 * 글 번호(no)에 해당하는 BoardSpringVO 타입의 
	 * 객체를 detail_main.jsp 로 보낸다. 
	 * db savefilename 컬럼은 파일이 하나 이상일 경우 콤마(,) 로 구분하였기 때문에
	 * StringTokenizer(fileName,",") 로 콤마(,) 단위로 나눈 후
	 * while 문을 사용해 파일명을 하나씩 List 에 담아 전송한다.
	 * @param no
	 * @return
	 * @throws Exception
	 */
	@RequestMapping("showContentNoHits.inven")
	public ModelAndView showContentNoHits(int no) throws Exception{
		ModelAndView mv = new ModelAndView();
		BoardSpringVO bvo = service.showSpringBoardNoHits(no);
		String fileName = bvo.getSaveFileName();
		if(fileName!=null){
			StringTokenizer st = new StringTokenizer(fileName,",");
			List<String> file = new ArrayList<String>();
			while(st.hasMoreTokens()) {
				String f = st.nextToken();
				file.add(f);
			}
			mv.addObject("saveFileName", file);
		}
		mv.addObject("vo", bvo);
		mv.addObject("info", memberService.showMyInfo(bvo.getId()));
		mv.addObject("reply", boardReplyService.getReplyList(no));
		mv.setViewName("detail.tiles");
		return mv;
	}
	/**
	 * showContentHit
	 * 게시물의 조회수(hits)를 증가시키고 글의 내용을 보여준다.
	 * 이하 showContentNoHit 과 동일
	 */
	@RequestMapping("showContentHits.inven")
	public ModelAndView showContentHits(int no) throws Exception{
		ModelAndView mv = new ModelAndView();
		BoardSpringVO bvo = service.showSpringBoardHits(no);
		String fileName = bvo.getSaveFileName();
		if(fileName!=null){
			StringTokenizer st = new StringTokenizer(fileName,",");
			List<String> file = new ArrayList<String>();
			while(st.hasMoreTokens()) {
				String f = st.nextToken();
				file.add(f);
			}
			mv.addObject("saveFileName", file);
		}
		mv.addObject("vo", bvo);
		mv.addObject("info", memberService.showMyInfo(bvo.getId()));
		System.out.println(memberService.showMyInfo(bvo.getId()));
		mv.addObject("reply", boardReplyService.getReplyList(no));
		mv.setViewName("detail.tiles");
		return mv;
	}
	/**
	 * fileDownload
	 * 파일 다운로드 링크
	 * downloadView 는 jsp 가 아닌 webbrow.board.util 의 downloadView Class 로 이동한다.
	 */
	@RequestMapping("fileDownload.inven")
	public ModelAndView fileDownload(String filename) throws Exception{
		HashMap map=new HashMap();
		map.put("path", path); // DownloadView 객체에 path 정보를 전달한다.
		return new ModelAndView("downloadView", map);
	}
	/**
	 * deleteContent
	 * db orgfilename, savefilename 컬럼에
	 * 파일이 하나 이상일 경우 콤마(,) 로 구분하였기 때문에
	 * StringTokenizer(saveFileName, ",") 로 파일이름을 
	 * 콤마(,) 단위로 나눈 후 while 문을 이용하여 하나씩 삭제한다.
	 */
	@RequestMapping("delete.inven")
	public ModelAndView deleteContent(int no, String saveFileName, String category, String contentType) throws Exception{
		System.out.println("컨트롤러 딜리트 : "+no+" "+saveFileName);
		boardReplyService.deleteReplyList(no);//글에 달린 댓글 목록 삭제
		boardReportService.deleteReport(no); // 글에 신고내역을 삭제
		service.deletePost(no);	// db 에 모든 데이터 삭제
		if(saveFileName!=null){ // 업로드 된 파일이 존재하면
			StringTokenizer st = new StringTokenizer(saveFileName, ",");	// 콤마(,) 를 제거
			while(st.hasMoreTokens()){	// 콤마(,) 뒤에 파일이 있을 때 까지
				String fileName = st.nextToken();	// 변수 fileName 에 파일명을 저장
				File file=new File(path+fileName);
				file.delete();	// 파일 삭제
				}
			}
		return new ModelAndView("redirect:/board.inven?category="+category+"&contentType="+contentType);
	}
	//게시판 리스트 보여주는 페이지
		@RequestMapping("board.inven")
		public ModelAndView boardInven(CategoryVO cvo) {
			System.out.println("다음페이지 보기"+cvo);
			if(cvo.getNo()==0){
				cvo.setNo(1);
				System.out.println(cvo);
			}
			ListVO lvo = service.getPostingList(cvo);
			System.out.println("리스트 보기"+lvo);
			return new ModelAndView("list.tiles", "lvo",lvo);
		}

		@RequestMapping("comment.inven")
		public String comment(CategoryVO cvo){
			return "comment.tiles";
		}
		@RequestMapping("writeComment.inven")
		public ModelAndView writeComment(BoardSpringVO vo, MultiFileVO mvo) throws Exception{
			System.out.println("댓글 컨트롤 : "+vo);
			List<MultipartFile> list=mvo.getFile();	
			String nameList[]=new String[list.size()];
			String fnStr="";
			String saveStr="";
			for(int i=0;i<list.size();i++){
				String fileName=list.get(i).getOriginalFilename();
				if(!fileName.isEmpty()){
					String newfilename=System.currentTimeMillis()+"_"+fileName;
					if(i==0) {
						fnStr+=fileName;
						saveStr+=newfilename;
					} else {
						fnStr+=","+fileName;
						saveStr+=","+newfilename;
					}
					list.get(i).transferTo(new File(path+newfilename));
					nameList[i]=fileName;
					vo.setOrgFileName(fnStr);
					vo.setSaveFileName(saveStr);
				}
			}
			service.writeComment(vo);
			return new ModelAndView("redirect:/showContentNoHits.inven?no="+vo.getNo());
		}
		
		@RequestMapping("writeNotice.inven")
		public ModelAndView writeNotice(BoardSpringVO vo) throws Exception {
			System.out.println("notice"+vo);
			service.writeSpringBoard(vo);
			return new ModelAndView("redirect:/showContentNoHits.inven?no="+vo.getNo());
		}
		
		//////////////////////////////////////////////////업데이트 부분///////////////////////////////////////////////
		 //글 수정하기
	@RequestMapping("updateContent.inven")
	public ModelAndView updateContent(BoardSpringVO vo, MultiFileVO mvo) throws Exception {
		ModelAndView mv = new ModelAndView();
		//System.out.println("mvo"+mvo);
		
		//MultiFileVO를 통해 들어온 파일의 리스트를 저장할 변수 saveList,orgList
		ArrayList<String> saveList = new ArrayList<String>();
		ArrayList<String> orgList = new ArrayList<String>();
		
		//MultiFileVO에 파일이 들어왔을 경우 그 파일을 orgList,saveList에 저장한다.
		if(mvo.getFile()!=null){
			List<MultipartFile> list = mvo.getFile();
			//System.out.println("업데이트 테스트 들어온 리스트 사이즈 : "+list.size());
			for (int i = 0; i < list.size(); i++) {
				String fileName = list.get(i).getOriginalFilename();
				//System.out.println("들어온 파일 이름 : "+fileName);
				if (!fileName.isEmpty()) {
					String newfilename = System.currentTimeMillis() + "_"+ fileName;
					//System.out.println("저장될 파일 이름 : "+newfilename);
					list.get(i).transferTo(new File(path + newfilename));
					saveList.add(newfilename);
					orgList.add(fileName);
				}
			}
		}
		
		if (orgList.size() != 0) {//MultiPartFile을 통해서 파일이 들어왔을 때
			
			//DB에 있는 orgFileList,saveFileList를 담을 변수 orgBufferList, saveBufferList
			ArrayList<String> orgBufferList = new ArrayList<String>();
			ArrayList<String> saveBufferList = new ArrayList<String>();
			String orgFileNameDB = service.getOrgFileNameListByNo(vo.getNo());
			//System.out.println("현재 DB에 저장된 orgFileNameDB : "+orgFileNameDB);
			
			if(orgFileNameDB==null){//DB에 orgFileName이 null일 경우(원본 글이 파일을 하나도 가지지 않았을 때)
				vo.setOrgFileName(this.toString(orgList));
			}else if(orgFileNameDB==""){//DB에 orgFileName이 공란일 경우(원본 글을 모두 지운 경우)
				vo.setOrgFileName(this.toString(orgList));
			}else{//DB에 저장된 파일이 있을 때
				orgBufferList = this.fileTokenizer(orgFileNameDB);//DB에 파일을 fileTokenizer로 잘라서 orgBufferList에 담는다.
				for (int i = 0; i < orgList.size(); i++) {
					orgBufferList.add(orgList.get(i));
				}
				vo.setOrgFileName(this.toString(orgBufferList));//view에서 받아온 vo 값에 set 메소드로 orgFileName을 저장
				//System.out.println("현재 DB에 저장된 orgFileNameDB를 잘라낸 값 :"+ orgBufferList);
			}
			
			String saveFileNameDB = service.getSaveFileNameListByNo(vo.getNo());
			//System.out.println("현재 DB에 저장된 saveFileNameDB : "+saveFileNameDB);
			
			if(saveFileNameDB==null){//DB에 saveFileName이 null일 경우(원본 글이 파일을 하나도 가지지 않았을 때)
				vo.setSaveFileName(this.toString(saveList));
			}else if(saveFileNameDB==""){//DB에 saveFileName이 공란일 경우(원본 글을 모두 지운 경우)
				vo.setSaveFileName(this.toString(saveList));
			}else{//DB에 저장된 파일이 있을 때
				saveBufferList = this.fileTokenizer(saveFileNameDB);//DB에 파일을 fileTokenizer로 잘라서 saveBufferList에 담는다.
				for (int i = 0; i < saveList.size(); i++) {
					saveBufferList.add((String) saveList.get(i));
				}
				vo.setSaveFileName(this.toString(saveBufferList));//view에서 받아온 vo 값에 set 메소드로 saveFileName을 저장
				//System.out.println("현재 DB에 저장된 saveFileNameDB를 잘라낸 값 :"+ saveBufferList);
			}
			
			//System.out.println("현재 DB에 값이 있을때 들어갈값 : "+this.toString(orgBufferList)+" "+this.toString(saveBufferList));
			//System.out.println("현재 DB에 값이 없을때 들어갈값 : "+this.toString(orgList)+" "+this.toString(saveList));
			service.updateSpringBoard(vo);//업데이트 실행
		}else{//MultiPartFile을 통해서 파일이 들어오지 않은 경우
			//System.out.println("파일이 안들어왔으면 파일 변화 없이 업데이트");
			service.updateSpringBoardNoFileChange(vo);
		}
		BoardSpringVO bvo = service.showSpringBoardNoHits(vo.getNo());
		//System.out.println("업데이트 실행후 vo값 확인 : " + bvo);
		
		mv.addObject("vo", bvo);
		mv.addObject("saveFileName", service.getOrgFileNameListByNo(vo.getNo()));//saveFileName에 orgFileName을 저장
		mv.setViewName("detail.tiles");
		return mv;

	}
		/**
		 * 파일의 변화가 없는 경우  orgFileName,saveFileName을 제외하고 글을 업데이트
		 */
		@RequestMapping("updateContentNoFileChange.inven")
		public ModelAndView updateContentNoFileChange(BoardSpringVO vo) throws Exception{
			System.out.println("updateContentNoFileChange"+vo);
			service.updateSpringBoardNoFileChange(vo);
			return new ModelAndView("redirect:/showContentNoHits.inven?no="+vo.getNo());
		}
		
		/**
		 * 글 수정을 하기 위해 페이지에 글 정보를 뿌려주는 메소드
		 * 만약 bvo.getOrgFileName() 값이 들어가 있으면 Tokenizer로 잘라서 view페이지에 보내준다.
		 */
		@RequestMapping("updateView.inven")
		public ModelAndView updateView(int no){
			ModelAndView mv = new ModelAndView();
			System.out.println(service.updateView(no));
			BoardSpringVO bvo = service.updateView(no);
			if(bvo.getSaveFileName()!=null){//saveFileName에 file이 들어있을 경우 list로 잘라낸다.
				ArrayList<String> saveList = this.fileTokenizer(bvo.getSaveFileName());
				ArrayList<String> orgList = this.fileTokenizer(bvo.getOrgFileName());
				mv.addObject("saveList", saveList);
				mv.addObject("orgList", orgList);
			}
			mv.addObject("bvo", bvo);
			mv.setViewName("update.tiles");
			return mv;
		}
	
	/**
	 * 실제 파일을 삭제하고 DB 정보를 업데이트
	 * 파일 하나를 삭제할때마다 호출되어 파일을 삭제하고 DB 정보를 갱신시킨다.
	 * 파일을 삭제한 후 다시 원래 페이지로 이동
	 */
	@RequestMapping("deleteFile.inven")
	@ResponseBody
	@Transactional
	public int deleteFile(int no, String orgFileName) {

		int index = 0;
		String orgFileNameDB = service.getOrgFileNameListByNo(no);
		ArrayList orgList = this.fileTokenizer(orgFileNameDB);//DB에 저장된 orgFileNameDB를 잘라서 orgList에 저장
		index = orgList.indexOf(orgFileName);//몇번째 인덱스를 지우는지 확인
		orgList.remove(orgFileName);//orgFileName에 해당하는 파일을 리스트에서 삭제
		
		String saveFileNameDB = service.getSaveFileNameListByNo(no);
		ArrayList saveList = this.fileTokenizer(saveFileNameDB);//DB에 저장된 saveFileNameDB를 잘라서 orgList에 저장
		String saveFileName = (String)saveList.get(index);//orgList의 인덱스면 saveFileName의 인덱스와 동일하다.
		saveList.remove(saveFileName);//saveFileName에 해당하는 파일을 리스트에서 삭제
		
		File file=new File(path+saveFileName);//path+파일명으로 file에 저장
		file.delete();	// 파일 삭제
		
		service.updateSaveFileName(no,this.toString(saveList));//DB의 saveFileName을 갱신
		service.updateOrgFileName(no,this.toString(orgList));//DB의 orgFileName을 갱신
		return 1;
	}
	
	/**
	 * orgFileName과 saveFileName을 한줄로 바꿔주는 메소드
	 * @param list
	 * @return
	 */
	public String toString(ArrayList list){
		String str="";
		switch(list.size()){
			case 1 : str=(String) list.get(0); break;
			case 2 : str=list.get(0)+","+list.get(1); break;
			case 3 : str=list.get(0)+","+list.get(1)+","+list.get(2); break;
			default : break;
		}
		return str;
	}
	
	/**
	 * 한줄로 연결된 fileName을 쉼표 단위로 잘라서 list에 넣어주는 메소드
	 * @param fileName
	 * @return
	 */
	public ArrayList<String> fileTokenizer(String fileName){
		StringTokenizer st = new StringTokenizer(fileName,",");
		ArrayList<String> list = new ArrayList<String>();
		while(st.hasMoreTokens()) {
			String str = st.nextToken();
			list.add(str);
		}
		return list;
	}
}
